package com.fast.alden.common.service.impl;

import com.fast.alden.common.exception.BizException;
import com.fast.alden.common.exception.BizExceptionEnum;
import com.fast.alden.common.service.BaseTreeNodeEntityService;
import com.fast.alden.data.model.BaseTreeNodeEntity;
import com.fast.alden.data.model.ITreeNode;
import com.fast.alden.data.repo.BaseEntityRepository;
import jakarta.annotation.Resource;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;

import java.util.ArrayList;
import java.util.List;

public abstract class BaseTreeNodeEntityServiceImpl<E extends BaseTreeNodeEntity, R extends BaseEntityRepository<E>> extends BaseEntityServiceImpl<E, R> implements BaseTreeNodeEntityService<E, R> {
    @Resource
    private EntityManager entityManager;

    @Override
    public List<E> tree() {
        List<E> list = this.list();
        return buildTreeList(list);
    }

    @Override
    @Transactional
    public E create(E entity) {
        if (entity == null) {
            throw new BizException(BizExceptionEnum.ENTITY_IS_NULL);
        }
        // 设置树形结构相关属性
        setParent(entity);
        return super.create(entity);
    }

    @Override
    @Transactional
    public E update(E entity) {
        if (entity == null) {
            throw new BizException(BizExceptionEnum.ENTITY_IS_NULL);
        }
        if (entity.getId() == null) {
            throw new BizException(BizExceptionEnum.ENTITY_ID_IS_NULL);
        }
        this.retrieveWithException(entity.getId());
        // 设置树形结构相关属性
        setParent(entity);
        return super.update(entity);
    }

    /**
     * 设置父节点信息
     *
     * @param entity 当前节点
     */
    protected void setParent(E entity) {
        if (!(entity instanceof ITreeNode treeNode)) {
            throw new BizException(BizExceptionEnum.ENTITY_IS_NOT_TREE_NODE);
        }
        if (entity.getId() == null) {
            entityManager.persist(entity);
        }
        if (treeNode.getParentId() != null) {
            if (treeNode.getParentId().equals(entity.getId())) {
                throw new BizException(BizExceptionEnum.PARENT_NODE_CAN_NOT_BE_SELF);
            }
            ITreeNode parent = this.retrieveWithException(treeNode.getParentId());
            treeNode.setParentId(parent.getId());
            treeNode.setRootId(parent.getRootId());
            treeNode.setIdPath(parent.getIdPath() + ITreeNode.ID_PATH_SEPARATOR + treeNode.getId());
        } else {
            // 根级节点rootId为自己
            treeNode.setRootId(entity.getId());
            treeNode.setIdPath(ITreeNode.ID_PATH_SEPARATOR + entity.getId());
        }
    }

    protected List<E> buildTreeList(List<E> list) {
        if (list == null) {
            return null;
        }
        List<Long> ids = list.stream().map(BaseTreeNodeEntity::getId).toList();
        List<E> resultList = new ArrayList<>();
        for (E node : list) {
            //如果是顶层节点
            if (node.getParentId() == null || !ids.contains(node.getParentId())) {
                resultList.add(node);
            }
            for (E child : list) {
                if (node.getId().equals(child.getParentId())) {
                    List<BaseTreeNodeEntity> children = node.getChildren();
                    if (children == null) {
                        children = new ArrayList<>();
                        node.setChildren(children);
                    }
                    children.add(child);
                }
            }
        }
        return resultList;
    }
}
